package dao

import (
	"context"

	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"

	"goldtree/internal/entity"
)

// StrategyDao 策略数据访问对象
type StrategyDao struct{}

var Strategy = StrategyDao{}

// Insert 创建策略
func (dao *StrategyDao) Insert(ctx context.Context, strategy *entity.Strategy) (int64, error) {
	// 排除ID字段，让数据库自动生成
	result, err := g.DB().Model("strategies").Ctx(ctx).Data(strategy).OmitEmpty().Insert()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// Update 更新策略
func (dao *StrategyDao) Update(ctx context.Context, id int, strategy *entity.Strategy) error {
	strategy.UpdatedAt = gtime.Now()
	_, err := g.DB().Model("strategies").Ctx(ctx).Where("id", id).Data(strategy).Update()
	return err
}

// Delete 删除策略
func (dao *StrategyDao) Delete(ctx context.Context, id int) error {
	_, err := g.DB().Model("strategies").Ctx(ctx).Where("id", id).Delete()
	return err
}

// GetById 根据ID获取策略
func (dao *StrategyDao) GetById(ctx context.Context, id int) (*entity.Strategy, error) {
	var strategy *entity.Strategy
	err := g.DB().Model("strategies").Ctx(ctx).Where("id", id).Scan(&strategy)
	if err != nil {
		return nil, err
	}
	return strategy, nil
}

// GetByName 根据名称获取策略
func (dao *StrategyDao) GetByName(ctx context.Context, name string) (*entity.Strategy, error) {
	var strategy *entity.Strategy
	err := g.DB().Model("strategies").Ctx(ctx).Where("name", name).Scan(&strategy)
	if err != nil {
		return nil, err
	}
	return strategy, nil
}

// GetList 获取策略列表
func (dao *StrategyDao) GetList(ctx context.Context, page, limit int, conditions ...interface{}) ([]*entity.Strategy, error) {
	model := g.DB().Model("strategies").Ctx(ctx)
	
	// 添加查询条件
	if len(conditions) > 0 {
		model = model.Where(conditions[0], conditions[1:]...)
	}
	
	var strategies []*entity.Strategy
	err := model.Order("created_at DESC").Limit((page-1)*limit, limit).Scan(&strategies)
	if err != nil {
		return nil, err
	}
	return strategies, nil
}

// GetCount 获取策略总数
func (dao *StrategyDao) GetCount(ctx context.Context, conditions ...interface{}) (int, error) {
	model := g.DB().Model("strategies").Ctx(ctx)
	
	// 添加查询条件
	if len(conditions) > 0 {
		model = model.Where(conditions[0], conditions[1:]...)
	}
	
	count, err := model.Count()
	if err != nil {
		return 0, err
	}
	return count, nil
}

// GetActiveStrategies 获取激活的策略列表
func (dao *StrategyDao) GetActiveStrategies(ctx context.Context) ([]*entity.Strategy, error) {
	var strategies []*entity.Strategy
	err := g.DB().Model("strategies").Ctx(ctx).Where("is_active", true).Order("created_at DESC").Scan(&strategies)
	if err != nil {
		return nil, err
	}
	return strategies, nil
}

// GetRunningStrategies 获取运行中的策略列表
func (dao *StrategyDao) GetRunningStrategies(ctx context.Context) ([]*entity.Strategy, error) {
	var strategies []*entity.Strategy
	err := g.DB().Model("strategies").Ctx(ctx).Where("status", "running").Order("created_at DESC").Scan(&strategies)
	if err != nil {
		return nil, err
	}
	return strategies, nil
}

// UpdateStatus 更新策略状态
func (dao *StrategyDao) UpdateStatus(ctx context.Context, id int, status string) error {
	data := g.Map{
		"status":     status,
		"updated_at": gtime.Now(),
	}
	_, err := g.DB().Model("strategies").Ctx(ctx).Where("id", id).Data(data).Update()
	return err
}

// UpdateRunInfo 更新策略运行信息
func (dao *StrategyDao) UpdateRunInfo(ctx context.Context, id int, runCount, errorCount int, lastError string) error {
	data := g.Map{
		"run_count":   runCount,
		"error_count": errorCount,
		"last_error":  lastError,
		"updated_at":  gtime.Now(),
	}
	_, err := g.DB().Model("strategies").Ctx(ctx).Where("id", id).Data(data).Update()
	return err
}

// IsNameExists 检查策略名称是否存在
func (dao *StrategyDao) IsNameExists(ctx context.Context, name string) (bool, error) {
	count, err := g.DB().Model("strategies").Ctx(ctx).Where("name", name).Count()
	if err != nil {
		return false, err
	}
	return count > 0, nil
}

// GetTypeList 获取策略类型列表
func (dao *StrategyDao) GetTypeList(ctx context.Context) ([]string, error) {
	var types []string
	err := g.DB().Model("strategies").Ctx(ctx).Fields("DISTINCT type").Scan(&types)
	if err != nil {
		return nil, err
	}
	return types, nil
}

// StrategyLogDao 策略日志数据访问对象
type StrategyLogDao struct{}

var StrategyLog = StrategyLogDao{}

// Insert 创建策略日志
func (dao *StrategyLogDao) Insert(ctx context.Context, log *entity.StrategyLog) (int64, error) {
	result, err := g.DB().Model("strategy_logs").Ctx(ctx).Data(log).Insert()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// GetListByStrategyId 根据策略ID获取日志列表
func (dao *StrategyLogDao) GetListByStrategyId(ctx context.Context, strategyId int, page, limit int) ([]*entity.StrategyLog, error) {
	var logs []*entity.StrategyLog
	err := g.DB().Model("strategy_logs").Ctx(ctx).
		Where("strategy_id", strategyId).
		Order("created_at DESC").
		Limit((page-1)*limit, limit).
		Scan(&logs)
	if err != nil {
		return nil, err
	}
	return logs, nil
}

// GetCountByStrategyId 根据策略ID获取日志总数
func (dao *StrategyLogDao) GetCountByStrategyId(ctx context.Context, strategyId int) (int, error) {
	count, err := g.DB().Model("strategy_logs").Ctx(ctx).Where("strategy_id", strategyId).Count()
	if err != nil {
		return 0, err
	}
	return count, nil
}

// DeleteOldLogs 删除旧日志
func (dao *StrategyLogDao) DeleteOldLogs(ctx context.Context, days int) error {
	_, err := g.DB().Model("strategy_logs").Ctx(ctx).
		Where("created_at < ?", gtime.Now().AddDate(0, 0, -days)).
		Delete()
	return err
}

// TradingSignalDao 交易信号数据访问对象
type TradingSignalDao struct{}

var TradingSignal = TradingSignalDao{}

// Insert 创建交易信号
func (dao *TradingSignalDao) Insert(ctx context.Context, signal *entity.TradingSignal) (int64, error) {
	result, err := g.DB().Model("trading_signals").Ctx(ctx).Data(signal).Insert()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// Update 更新交易信号
func (dao *TradingSignalDao) Update(ctx context.Context, id int, signal *entity.TradingSignal) error {
	_, err := g.DB().Model("trading_signals").Ctx(ctx).Where("id", id).Data(signal).Update()
	return err
}

// GetById 根据ID获取交易信号
func (dao *TradingSignalDao) GetById(ctx context.Context, id int) (*entity.TradingSignal, error) {
	var signal *entity.TradingSignal
	err := g.DB().Model("trading_signals").Ctx(ctx).Where("id", id).Scan(&signal)
	if err != nil {
		return nil, err
	}
	return signal, nil
}

// GetListByStrategyId 根据策略ID获取交易信号列表
func (dao *TradingSignalDao) GetListByStrategyId(ctx context.Context, strategyId int, page, limit int) ([]*entity.TradingSignal, error) {
	var signals []*entity.TradingSignal
	err := g.DB().Model("trading_signals").Ctx(ctx).
		Where("strategy_id", strategyId).
		Order("created_at DESC").
		Limit((page-1)*limit, limit).
		Scan(&signals)
	if err != nil {
		return nil, err
	}
	return signals, nil
}

// GetPendingSignals 获取待处理的交易信号
func (dao *TradingSignalDao) GetPendingSignals(ctx context.Context) ([]*entity.TradingSignal, error) {
	var signals []*entity.TradingSignal
	err := g.DB().Model("trading_signals").Ctx(ctx).
		Where("status", "pending").
		Order("created_at ASC").
		Scan(&signals)
	if err != nil {
		return nil, err
	}
	return signals, nil
}

// UpdateStatus 更新交易信号状态
func (dao *TradingSignalDao) UpdateStatus(ctx context.Context, id int, status string, executedAt *gtime.Time) error {
	data := g.Map{
		"status": status,
	}
	if executedAt != nil {
		data["executed_at"] = executedAt
	}
	_, err := g.DB().Model("trading_signals").Ctx(ctx).Where("id", id).Data(data).Update()
	return err
}

// GetList 获取交易信号列表
func (dao *TradingSignalDao) GetList(ctx context.Context, page, limit int, conditions ...interface{}) ([]*entity.TradingSignal, error) {
	model := g.DB().Model("trading_signals").Ctx(ctx)
	
	// 添加查询条件
	if len(conditions) > 0 {
		model = model.Where(conditions[0], conditions[1:]...)
	}
	
	var signals []*entity.TradingSignal
	err := model.Order("created_at DESC").Limit((page-1)*limit, limit).Scan(&signals)
	if err != nil {
		return nil, err
	}
	return signals, nil
}

// GetCount 获取交易信号总数
func (dao *TradingSignalDao) GetCount(ctx context.Context, conditions ...interface{}) (int, error) {
	model := g.DB().Model("trading_signals").Ctx(ctx)
	
	// 添加查询条件
	if len(conditions) > 0 {
		model = model.Where(conditions[0], conditions[1:]...)
	}
	
	count, err := model.Count()
	if err != nil {
		return 0, err
	}
	return count, nil
}

// StrategyPerformanceDao 策略性能数据访问对象
type StrategyPerformanceDao struct{}

var StrategyPerformance = StrategyPerformanceDao{}

// Insert 创建策略性能记录
func (dao *StrategyPerformanceDao) Insert(ctx context.Context, performance *entity.StrategyPerformanceEntity) (int64, error) {
	result, err := g.DB().Model("strategy_performance").Ctx(ctx).Data(performance).Insert()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// Update 更新策略性能记录
func (dao *StrategyPerformanceDao) Update(ctx context.Context, strategyId int, performance *entity.StrategyPerformanceEntity) error {
	performance.UpdatedAt = gtime.Now()
	_, err := g.DB().Model("strategy_performance").Ctx(ctx).Where("strategy_id", strategyId).Data(performance).Update()
	return err
}

// Upsert 插入或更新策略性能记录
func (dao *StrategyPerformanceDao) Upsert(ctx context.Context, performance *entity.StrategyPerformanceEntity) error {
	var existing *entity.StrategyPerformanceEntity
	err := g.DB().Model("strategy_performance").Ctx(ctx).Where("strategy_id", performance.StrategyId).Scan(&existing)
	if err != nil {
		return err
	}
	
	if existing == nil {
		_, err = dao.Insert(ctx, performance)
	} else {
		err = dao.Update(ctx, performance.StrategyId, performance)
	}
	return err
}

// GetByStrategyId 根据策略ID获取性能记录
func (dao *StrategyPerformanceDao) GetByStrategyId(ctx context.Context, strategyId int) (*entity.StrategyPerformanceEntity, error) {
	var performance *entity.StrategyPerformanceEntity
	err := g.DB().Model("strategy_performance").Ctx(ctx).Where("strategy_id", strategyId).Scan(&performance)
	if err != nil {
		return nil, err
	}
	return performance, nil
}

// StrategyPositionDao 策略持仓数据访问对象
type StrategyPositionDao struct{}

var StrategyPosition = StrategyPositionDao{}

// Insert 创建策略持仓记录
func (dao *StrategyPositionDao) Insert(ctx context.Context, position *entity.StrategyPosition) (int64, error) {
	result, err := g.DB().Model("strategy_positions").Ctx(ctx).Data(position).Insert()
	if err != nil {
		return 0, err
	}
	return result.LastInsertId()
}

// Update 更新策略持仓记录
func (dao *StrategyPositionDao) Update(ctx context.Context, id int, position *entity.StrategyPosition) error {
	position.LastUpdate = gtime.Now()
	_, err := g.DB().Model("strategy_positions").Ctx(ctx).Where("id", id).Data(position).Update()
	return err
}

// GetByStrategyAndStock 根据策略ID和股票代码获取持仓记录
func (dao *StrategyPositionDao) GetByStrategyAndStock(ctx context.Context, strategyId int, stockCode string) (*entity.StrategyPosition, error) {
	var position *entity.StrategyPosition
	err := g.DB().Model("strategy_positions").Ctx(ctx).
		Where("strategy_id", strategyId).
		Where("stock_code", stockCode).
		Scan(&position)
	if err != nil {
		return nil, err
	}
	return position, nil
}

// GetListByStrategyId 根据策略ID获取持仓列表
func (dao *StrategyPositionDao) GetListByStrategyId(ctx context.Context, strategyId int) ([]*entity.StrategyPosition, error) {
	var positions []*entity.StrategyPosition
	err := g.DB().Model("strategy_positions").Ctx(ctx).
		Where("strategy_id", strategyId).
		Where("quantity > 0").
		Order("last_update DESC").
		Scan(&positions)
	if err != nil {
		return nil, err
	}
	return positions, nil
}

// Delete 删除持仓记录
func (dao *StrategyPositionDao) Delete(ctx context.Context, id int) error {
	_, err := g.DB().Model("strategy_positions").Ctx(ctx).Where("id", id).Delete()
	return err
}

// UpdatePrice 更新持仓价格信息
func (dao *StrategyPositionDao) UpdatePrice(ctx context.Context, id int, currentPrice, marketValue, pnl, pnlRatio float64) error {
	data := g.Map{
		"current_price": currentPrice,
		"market_value":  marketValue,
		"pnl":           pnl,
		"pnl_ratio":     pnlRatio,
		"last_update":   gtime.Now(),
	}
	_, err := g.DB().Model("strategy_positions").Ctx(ctx).Where("id", id).Data(data).Update()
	return err
}